package net.csdn.business.kanban.api.facade;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import lombok.RequiredArgsConstructor;
import net.csdn.business.kanban.api.entity.KanbanField;
import net.csdn.business.kanban.api.entity.KanbanFieldExtension;
import net.csdn.business.kanban.api.entity.KanbanView;
import net.csdn.business.kanban.api.enums.FieldTypeEnums;
import net.csdn.business.kanban.api.service.*;
import net.csdn.business.kanban.common.domain.request.*;
import net.csdn.business.kanban.common.domain.resp.KanbanFieldResp;
import net.csdn.business.kanban.common.enums.ResultCodeEnum;
import net.csdn.business.kanban.common.utils.ExceptionUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName KanbanFieldFacade
 * @Description TODO
 * @Author liuzhisheng
 * @Date 2023/9/19
 **/
@Service
@RequiredArgsConstructor
public class KanbanFieldFacade {
    private final KanbanFieldService kanbanFieldService;
    private final KanbanFieldExtensionService kanbanFieldExtensionService;
    private final KanbanViewService kanbanViewService;
    private final KanbanDetailService kanbanDetailService;

    @Value("${kanban.detail.arrange.limit}")
    private long arrangeLimit;
    /**
     * 获取自定义字段列表
     * @param kanbanId
     * @return
     */
    public List<KanbanFieldResp> fieldSettings(String kanbanId){
        /**获取看板的所有定义字段*/
        List<KanbanField> kanbanFields = kanbanFieldService.getFieldsByKbId(kanbanId);
        /**获取看板的所有扩展属性字段*/
        List<KanbanFieldExtension> kanbanFieldExtensionList = kanbanFieldExtensionService.fieldExtensionsByKanbanId(kanbanId);

        List<KanbanFieldResp> respList = BeanUtil.copyToList(kanbanFields,KanbanFieldResp.class);
        respList.stream().forEach(bean ->{
            List<KanbanFieldExtension> attributes = kanbanFieldExtensionList.stream().filter(extension -> extension.getFieldId().equals(bean.getId())).collect(Collectors.toList());
            List<KanbanFieldExtensionParam> paramList = new ArrayList<>();
            attributes.forEach(attribute -> {
                KanbanFieldExtensionParam param = new KanbanFieldExtensionParam();
                param.setId(attribute.getId());
                param.setCreatedAt(attribute.getCreatedAt());
                param.setFieldId(attribute.getFieldId());
                param.setFieldProperties_json(JSON.parseObject(attribute.getFieldProperties()));
                paramList.add(param);
            });
            bean.setAttributes(paramList);
        });
        return respList;
    }

    /**
     * 新增自定义字段
     * @param kanbanFieldParam
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean addKanbanField(KanbanFieldParam kanbanFieldParam){
        /**判断该看板下字体个数。字段新增限制*/
        long countField = kanbanFieldService.countField(kanbanFieldParam.getKanbanId());
        if(countField >= arrangeLimit){
            ExceptionUtil.throwBizException(ResultCodeEnum.KANBAN_LIMIT_FIELD,"字段新增限数");
        }
        KanbanField kanbanField = new KanbanField();
        kanbanField.setKanbanId(kanbanFieldParam.getKanbanId());
        kanbanField.setCreatorId(kanbanFieldParam.getCurrUserId());
        kanbanField.setFieldType(kanbanFieldParam.getFieldType());
        kanbanField.setFieldName(kanbanFieldParam.getFieldName());
        kanbanField.setUserDefined(true);
        kanbanFieldService.save(kanbanField);

        List<KanbanFieldExtension> extensions = new ArrayList<>();
        if(FieldTypeEnums.SINGLE_SELECT.getCode().equals(kanbanFieldParam.getFieldType())){
            Optional.ofNullable(kanbanFieldParam.getFieldSettings()).ifPresent(fieldSettings -> {
                if(CollectionUtil.isNotEmpty(fieldSettings.getOptionsList())){
                    fieldSettings.getOptionsList().stream().forEach(options -> {
                        KanbanFieldExtension extension = new KanbanFieldExtension();
                        extension.setCreatorId(kanbanFieldParam.getCurrUserId());
                        extension.setKanbanId(kanbanFieldParam.getKanbanId());
                        extension.setFieldId(kanbanField.getId());
                        extension.setFieldProperties(JSON.toJSONString(options));
                        extension.setPriority(options.getPriority());
                        extensions.add(extension);
                    });
                }
            });
        }else if(FieldTypeEnums.ITERATION.getCode().equals(kanbanFieldParam.getFieldType())){
            Optional.ofNullable(kanbanFieldParam.getFieldSettings()).ifPresent(fieldSettings -> {
                if(CollectionUtil.isNotEmpty(fieldSettings.getIterationList())){
                    fieldSettings.getIterationList().stream().forEach(iteration -> {
                        KanbanFieldExtension extension = new KanbanFieldExtension();
                        extension.setKanbanId(kanbanFieldParam.getKanbanId());
                        extension.setFieldId(kanbanField.getId());
                        extension.setCreatorId(kanbanFieldParam.getCurrUserId());
                        extension.setFieldProperties(JSON.toJSONString(iteration));
                        extension.setPriority(iteration.getPriority());
                        extensions.add(extension);
                    });
                }
            });
        }
        /**批量添加字段扩展属性表*/
        if(CollectionUtil.isNotEmpty(extensions)){
            kanbanFieldExtensionService.saveBatch(extensions,extensions.size());
        }
        /**给看板下的所有view添加字段属性*/
        kanbanViewService.updateViewFieldDisplayJson(kanbanField.getId(),true,kanbanField.getKanbanId());
        return true;
    }

    /**
     * 删除自定义字段
     * @param fieldId
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteKanbanField(Long fieldId,String kanbanId){
        KanbanField kanbanField = kanbanFieldService.getById(fieldId);
        if(kanbanField == null){
            ExceptionUtil.throwBizException(ResultCodeEnum.RESOURCE_NOT_EXIST);
        }
        /**判断字段ID所在的看板是否是当前字段所在看板，防止串删*/
        if(!kanbanField.getKanbanId().equals(kanbanId)){
            ExceptionUtil.throwBizException(ResultCodeEnum.RESOURCE_NOT_EXIST);
        }
        /**非自定义字段无法删除*/
        if(!kanbanField.getUserDefined()){
            ExceptionUtil.throwBizException(ResultCodeEnum.KANBAN_NOT_USERDEFIEND);
        }
        /**删除字段表*/
        kanbanFieldService.removeById(fieldId);
        /**删除字段扩展表*/
        kanbanFieldExtensionService.removeByFieldId(fieldId);

        /**获取看板中所以view的字段数组，删掉数组中该字段对应的属性*/
        List<KanbanView> kanbanViews = kanbanViewService.getAllKanbanViews(kanbanField.getKanbanId());
        kanbanViews.forEach(bean -> {
            List<JSONObject> results = new ArrayList<>();
            List<JSONObject> objectList = JSON.parseArray(bean.getFieldDisplayJson(),JSONObject.class);
           objectList.forEach(obj -> {
               Set<Map.Entry<String, Object>> entries = obj.entrySet();
               for (Map.Entry<String, Object> str : entries) {
                   if(!str.getKey().equals(fieldId.toString())){
                       results.add(obj);
                   }
               }
           });
            bean.setFieldDisplayJson(JSON.toJSONString(results));
        });

        /**清除view表中字段属性*/
        List<KanbanView> updateFields = new ArrayList<>();
        kanbanViews.forEach(bean -> {
            KanbanView view = new KanbanView();
            view.setId(bean.getId());
            view.setFieldDisplayJson(bean.getFieldDisplayJson());
            updateFields.add(view);
        });
        kanbanViewService.updateBatchById(updateFields);

        /**删除看板下所有该字段的明细内容*/
        kanbanDetailService.removeFieldContentJson(kanbanId,fieldId);
        return true;
    }

    /**
     * 编辑字段信息
     * @param param
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean updateKanbanField(KanbanFieldUpdateParam param){
        KanbanField kanbanField = kanbanFieldService.getById(param.getFieldId());
        if(kanbanField == null){
            ExceptionUtil.throwBizException(ResultCodeEnum.RESOURCE_NOT_EXIST);
        }
        if(!kanbanField.getKanbanId().equals(param.getKanbanId())){
            ExceptionUtil.throwBizException(ResultCodeEnum.RESOURCE_NOT_EXIST);
        }
        if(!Objects.equals(kanbanField.getFieldName(),param.getFieldName())){
            /**更新字段表信息*/
            kanbanField.setFieldName(param.getFieldName());
            kanbanField.setUpdatedAt(null);
            kanbanFieldService.updateById(kanbanField);
        }
        List<KanbanFieldExtension> addList = new ArrayList<>();
        List<KanbanFieldExtension> updateList = new ArrayList<>();
        List<KanbanFieldExtension> removeList = new ArrayList<>();

        /**单选项更新*/
        if(FieldTypeEnums.SINGLE_SELECT.getCode().equals(kanbanField.getFieldType())){
            if(Objects.isNull(param.getFieldSettings()) || CollectionUtil.isEmpty(param.getFieldSettings().getOptionsList())){
                /**清楚全部的字段属性*/
                kanbanFieldExtensionService.removeByFieldId(kanbanField.getId());
            }else {
                /**查询该字段下所有的属性*/
                List<KanbanFieldExtension> extensionList =  kanbanFieldExtensionService.fieldExtensionsByFieadId(kanbanField.getKanbanId(),kanbanField.getId());
                /**刷选处已移除的属性*/
                extensionList.forEach(bean -> {
                    long count1 = param.getFieldSettings().getOptionsList().stream().filter(options -> bean.getId().equals(options.getId())).count();
                    if(count1 == 0){
                        removeList.add(bean);
                    }
                });
                param.getFieldSettings().getOptionsList().stream().forEach(optionl -> {
                    if(optionl.getId() == null){
                        KanbanFieldExtension kanbanFieldExtension = new KanbanFieldExtension();
                        kanbanFieldExtension.setFieldId(kanbanField.getId());
                        kanbanFieldExtension.setKanbanId(kanbanField.getKanbanId());
                        kanbanFieldExtension.setFieldProperties(JSON.toJSONString(optionl));
                        kanbanFieldExtension.setCreatorId(param.getCurrUserId());
                        kanbanFieldExtension.setPriority(optionl.getPriority());
                        addList.add(kanbanFieldExtension);
                    }else {
                        /**判断内容是否更新*/
                        Optional<KanbanFieldExtension> optiona2 = extensionList.stream().filter(bean -> bean.getId().equals(optionl.getId())).findFirst();
                        if(optiona2.isPresent()){
                            KanbanFieldExtension extension = optiona2.get();
                            SingleSelectAttribute attribute = JSON.parseObject(extension.getFieldProperties(), SingleSelectAttribute.class);
                            if(!(Objects.equals(attribute.getColor(),optionl.getColor()) && Objects.equals(attribute.getDesc(),optionl.getDesc())
                                    && Objects.equals(attribute.getName(),optionl.getName()) && Objects.equals(attribute.getPriority(),optionl.getPriority()))){
                                extension.setFieldProperties(JSON.toJSONString(optionl));
                                extension.setPriority(optionl.getPriority());
                                updateList.add(extension);
                            }
                        }
                    }
                });
            }
            /**迭代项更新*/
        }else if(FieldTypeEnums.ITERATION.getCode().equals(kanbanField.getFieldType())){
            if(Objects.isNull(param.getFieldSettings()) || CollectionUtil.isEmpty(param.getFieldSettings().getIterationList())){
                /**清楚全部的字段属性*/
                kanbanFieldExtensionService.removeByFieldId(kanbanField.getId());
            }else {
                /**查询该字段下所有的属性*/
                List<KanbanFieldExtension> extensionList =  kanbanFieldExtensionService.fieldExtensionsByFieadId(kanbanField.getKanbanId(),kanbanField.getId());
                /**刷选处已移除的属性*/
                extensionList.forEach(bean -> {
                    long count1 = param.getFieldSettings().getIterationList().stream().filter(iterations -> bean.getId().equals(iterations.getId())).count();
                    if(count1 == 0){
                        removeList.add(bean);
                    }
                });
                param.getFieldSettings().getIterationList().stream().forEach(iteration1 -> {
                    if(iteration1.getId() == null){
                        KanbanFieldExtension kanbanFieldExtension = new KanbanFieldExtension();
                        kanbanFieldExtension.setFieldId(kanbanField.getId());
                        kanbanFieldExtension.setKanbanId(kanbanField.getKanbanId());
                        kanbanFieldExtension.setFieldProperties(JSON.toJSONString(iteration1));
                        kanbanFieldExtension.setCreatorId(param.getCurrUserId());
                        kanbanFieldExtension.setPriority(iteration1.getPriority());
                        addList.add(kanbanFieldExtension);

                    }else {
                        /**判断内容是否更新*/
                        Optional<KanbanFieldExtension> optiona2 = extensionList.stream().filter(bean -> bean.getId().equals(iteration1.getId())).findFirst();
                        if(optiona2.isPresent()){
                            KanbanFieldExtension extension = optiona2.get();
                            IterationsAttribute attribute = JSON.parseObject(extension.getFieldProperties(), IterationsAttribute.class);
                            if(!(Objects.equals(attribute.getStartDate(),iteration1.getStartDate()) && Objects.equals(attribute.getDuration(),iteration1.getDuration())
                                    && Objects.equals(attribute.getTitle(),iteration1.getTitle()) && Objects.equals(attribute.getPriority(),iteration1.getPriority()))){
                                extension.setFieldProperties(JSON.toJSONString(iteration1));
                                extension.setPriority(iteration1.getPriority());
                                updateList.add(extension);
                            }
                        }
                    }
                });
            }
        }
        if(CollectionUtil.isNotEmpty(addList)){
            kanbanFieldExtensionService.saveBatch(addList);
        }
        if(CollectionUtil.isNotEmpty(updateList)){
            kanbanFieldExtensionService.updateBatchById(updateList);
        }
        if(CollectionUtil.isNotEmpty(removeList)){
            kanbanFieldExtensionService.removeBatchByIds(removeList);
        }
        return true;
    }

    /**
     * 获取自定义字段列表
     * @param kanbanId
     * @return
     */
    public List<KanbanFieldResp> fieldList(String kanbanId){
        /**获取看板的所有定义字段*/
        List<KanbanField> kanbanFields = kanbanFieldService.getFieldsByKbId(kanbanId);
        return BeanUtil.copyToList(kanbanFields,KanbanFieldResp.class);
    }

    /**
     * @Desc: 获取字段属性
     * @author:liuzhisheng
     * @date: 2023/10/16
     */
    public KanbanFieldResp fieldInfo(Long fieldId,String kanbanId){
        KanbanField kanbanField = kanbanFieldService.getById(fieldId);
        if(kanbanField != null){
            KanbanFieldResp resp = BeanUtil.copyProperties(kanbanField,KanbanFieldResp.class);
            List<KanbanFieldExtension> list = kanbanFieldExtensionService.fieldExtensionsByFieadId(kanbanId,fieldId);
            List<KanbanFieldExtensionParam> attributes = new ArrayList<>();
            list.forEach(bean -> {
                KanbanFieldExtensionParam param = BeanUtil.copyProperties(bean,KanbanFieldExtensionParam.class);
                param.setFieldProperties_json(JSON.parseObject(bean.getFieldProperties()));
                attributes.add(param);
            });
            resp.setAttributes(attributes);

            return resp;
        }
        return null;
    }
}
